#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

#define NUM 1024
#define SIZE 32
char command_line[NUM]; // 用来接收命令行内容
char* command_argv[SIZE]; // 用来储存命令行参数
char g_myval[64];// 写一个环境变量的buffer缓冲区

int main()
{
    while (1)
    {
        // 1. 打印显示提示符，比如：[rtx2@VM-8-14-centos linux_11_shell]$（这里就不获取了）    
        printf("[用户名@主机名 当前目录]# ");
        fflush(stdout);

        // 2. 获取用户输入的指令和选项，比如：" ls -a -l "，->用fgets
        memset(command_line,'\0',sizeof(command_line) * sizeof(char));
        if (fgets(command_line, NUM, stdin) == NULL) // 从键盘获取,stdin获取到C风格的字符串,默认添加\0
        {
            continue; // 读错了重新输入(基本不会读错)
        }
        command_line[strlen(command_line) - 1] = '\0';  // 消除 '\n'
        // printf("echo: %s\n", command_line); // 打印测试一下,后面注释掉
        
        // 3.拆开输入的命令和选项
        const char* dilim = " ";
        command_argv[0] = strtok(command_line, dilim); // 第一次调用，传入原始字符串
        int index = 1;
        if(strcmp(command_argv[0],"ls") == 0)
        {
            command_argv[index++] = "--color=auto"; // 成立的话下面while循环从2开始跑
        }
        while(command_argv[index++] = strtok(NULL, dilim)) // 第二次调用，如果还要拆开原来的字符串，传入NULL
        {
            ; // 最后strtok获得的是\0，跳出循环
        }
        /*for(int i = 0; command_argv[i]; ++i) // 用来测试，等下注释掉
        {
            printf("command[%d] = %s\n", i, command_argv[i]);
        }*/

        // 放置环境变量
        if(strcmp(command_argv[0], "export") == 0 && command_argv[1] != NULL)
        {
            strcpy(g_myval, command_argv[1]);
            int ret = putenv(g_myval);
            if(ret == 0)
            {
                printf("%s export success\n", command_argv[1]);
            }
            continue;
        }
        // 处理内置命令
        if(strcmp(command_argv[0], "cd") == 0)
        {
            if(command_argv[1] != NULL)
            {
                chdir(command_argv[1]);
            }
        }
        // 4.创建进程和程序替换执行命令
        pid_t id = fork();
        if(id == 0)
        {
            printf("myshell子进程执行的：\n");
            execvp(command_argv[0],command_argv); // 传入要执行的名字和数组
            exit(1); // 只要到这里,子进程一定是替换失败了
        }
        int status = 0; // 只有父进程走到这里
        pid_t ret = waitpid(id, &status, 0); // 阻塞等待
        if(ret > 0)
        {
            printf("父进程等待成功,exit code: %d\n", WEXITSTATUS(status));
        }
    }
    return 0;
}
